package cn.tedu.wallet.service.impl;

import cn.tedu.base.response.StatusCode;
import cn.tedu.base.utils.SnowFlakeUtil;
import cn.tedu.wallet.consts.TradeStatus;
import cn.tedu.wallet.consts.TradeType;
import cn.tedu.wallet.dao.repository.RecordRepository;
import cn.tedu.wallet.dao.repository.WalletRepository;
import cn.tedu.wallet.pojo.param.ArticlePayRecordParam;
import cn.tedu.wallet.pojo.param.RecordParam;
import cn.tedu.wallet.pojo.po.RecordMQPO;
import cn.tedu.wallet.pojo.po.UserTransactionRecordPO;
import cn.tedu.wallet.pojo.po.UserWalletPO;
import cn.tedu.wallet.pojo.vo.UserTransactionRecordVO;
import cn.tedu.wallet.service.rabbitMQ.RabbitMQRecordProducer;
import cn.tedu.wallet.service.RecordService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@Service
@Slf4j
public class RecordServiceImpl implements RecordService {

    @Autowired
    private RecordRepository recordRepository;

    @Autowired
    private WalletRepository walletRepository;

    @Autowired
    private RabbitMQRecordProducer rabbitMQRecordProducer;

    @Override
    public Integer addRecord(RecordParam param) {
        log.info("修改交易记录状态");
        //判断交易是否超时
        UserTransactionRecordPO d = recordRepository.getRecordDetail(param.getRecordId());
        if (!d.getTransactionStatus().equals(TradeStatus.ONGOING.getCode())) {
            return StatusCode.OPERATION_FAILED.getCode();
        }
        Date now = new Date();
        UserTransactionRecordPO recordPO = new UserTransactionRecordPO();
        // 判断是否为充值记录
        if (param.getPayerUserId().equals(param.getAccountUserId())) {
            BigDecimal balance = walletRepository.doGetBalance(param.getAccountUserId()).getBalance();
            BigDecimal newBalance = balance.add(param.getTransactionAmount());
            UserWalletPO po = new UserWalletPO();
            po.setUserId(param.getAccountUserId());
            po.setBalance(newBalance);
            po.setUpdateTime(now);
            walletRepository.updateBalance(po);
            BeanUtils.copyProperties(param, recordPO);
            recordPO.setId(param.getRecordId());
            recordPO.setCreateTime(now);
            recordPO.setUpdateTime(now);
            recordPO.setTransactionStatus(TradeStatus.SUCCESS.getCode());
            log.info("服务调用修改充值交易记录状态");
            recordRepository.updateRecord(recordPO);
            log.info("服务调用修改充值交易记录状态成功");
            return StatusCode.OPERATION_SUCCESS.getCode();
        }else {
            // 判断为消费记录
            UserWalletPO userWalletPO = new UserWalletPO();
            BigDecimal amount = recordRepository.getRecordDetail(param.getRecordId()).getTransactionAmount();
            // 消费者减少余额并更改消费记录状态
            log.info("amount:{}",amount);
            log.info("服务调用更新消费者余额操作");
            // 判断余额是否足够
            BigDecimal oldBalance = walletRepository.doGetBalance(param.getPayerUserId()).getBalance();
            if (oldBalance.compareTo(amount) < 0) {
                log.info("余额不足");
                // 返回余额不足
                UserTransactionRecordPO recordDetail = recordRepository.getRecordDetail(param.getRecordId());
                recordDetail.setTransactionStatus(TradeStatus.CANCELED.getCode());
                recordDetail.setUpdateTime(now);
                recordRepository.updateRecord(recordDetail);
                return StatusCode.INSUFFICIENT_FUNDS.getCode(); // TODO 正常情况下应当抛出余额不足的自定义异常，但gateway还没做全局异常处理
            }
            // 消费者减少余额并更改消费记录状态
            BigDecimal newBalance = oldBalance.subtract(amount);
            userWalletPO.setBalance(newBalance);
            userWalletPO.setUserId(param.getPayerUserId());
            userWalletPO.setUpdateTime(new Date());
            walletRepository.updateBalance(userWalletPO);


            log.info("服务调用更新消费记录的交易状态操作");
            UserTransactionRecordPO recordDetail = recordRepository.getRecordDetail(param.getRecordId());
            recordDetail.setTransactionStatus(TradeStatus.SUCCESS.getCode());
            recordDetail.setUpdateTime(now);
            recordRepository.updateRecord(recordDetail);


            // 文章作者增加余额新增收入记录
            log.info("服务调用更新文章作者余额操作");
            UserWalletPO writerWalletPO = walletRepository.doGetBalance(param.getAccountUserId());
            BigDecimal newBalance1 = writerWalletPO.getBalance().add(amount);
            BigDecimal earning = writerWalletPO.getEarnings().add(amount);
            userWalletPO.setEarnings(earning);
            userWalletPO.setBalance(newBalance1);
            userWalletPO.setUserId(param.getAccountUserId());
            userWalletPO.setUpdateTime(new Date());
            walletRepository.updateBalance(userWalletPO);

//            log.info("服务调用插入作者的收入交易记录");
//            BeanUtils.copyProperties(param, recordPO);
//            recordPO.setCreateTime(now);
//            recordPO.setId(SnowFlakeUtil.getId());
//            recordPO.setTransactionType(TradeType.NORMAL_TRADE.getCode());
//            recordPO.setTransactionStatus(TradeStatus.SUCCESS.getCode());
//            recordRepository.doAddRecord(recordPO);
//            log.info("文章作者收入记录插入成功");

            return StatusCode.OPERATION_SUCCESS.getCode();
        }
    }

    @Override
    public String prepareRecord(RecordParam param) {
        log.info("新增状态为交易中的交易记录");
        Long id = SnowFlakeUtil.getId();
        UserTransactionRecordPO recordPO = new UserTransactionRecordPO();
        // 插入状态为进行中的订单
        BeanUtils.copyProperties(param, recordPO);
        recordPO.setId(id);
        recordPO.setTransactionStatus(TradeStatus.ONGOING.getCode());
        if (param.getPayerUserId().equals(param.getAccountUserId())) {
            recordPO.setTransactionType(TradeType.RECHARGE.getCode());
        }else {
            recordPO.setTransactionType(TradeType.ARTICLE_TRADE.getCode());
        }
        recordPO.setCreateTime(new Date());
        BigDecimal amount = param.getTransactionAmount();
        recordPO.setTransactionAmount(amount);
        recordPO.setArticleId(param.getArticleId());
        recordRepository.doAddRecord(recordPO);
        sendRecordMessage(id);
        log.info("id:{}",id);
        return String.valueOf(id);
    }

    @Override
    public Integer SelectArticlePayRecord(ArticlePayRecordParam param) {
        log.info("查询文章{}的购买记录", param);
        UserTransactionRecordPO recordPO = recordRepository.doSelectArticlePayRecord(param.getUserId(), param.getArticleId());
        if (recordPO != null) {
            return 1; //临时处理 1为查询到文章
        }
        return 0; // 0为没有查询到
    }

    @Override
    public List<UserTransactionRecordVO> SelectUserPayRecord(Long userId) {
        log.info("查询用户{}的交易记录", userId);
        List<UserTransactionRecordPO> poList = recordRepository.doSelectUserPayRecord(userId);
        //遍历list 将list里的元素的accountUserId属性和userId属性不同的元素中的transactionAmount的数值取反
        ArrayList<UserTransactionRecordVO> voList = new ArrayList<>();
        DecimalFormat decimalFormat = new DecimalFormat("0.00");
        for (UserTransactionRecordPO po : poList) {
            UserTransactionRecordVO vo = new UserTransactionRecordVO();
            if (!po.getAccountUserId().equals(userId)) {
                po.setTransactionAmount(po.getTransactionAmount().negate());
                log.info("取反成功{}", po.getTransactionAmount());
            }
            BeanUtils.copyProperties(po, vo);
            String format = decimalFormat.format(po.getTransactionAmount().doubleValue());
            vo.setTransactionAmount(format);
            log.info(format);
            voList.add(vo);
        }
        log.info("查询用户{}的交易记录成功", voList);
        return voList;
    }

    @Override
    public Integer selectRecordStatus(Long recordId) {
        UserTransactionRecordPO recordDetail = recordRepository.getRecordDetail(recordId);
        return recordDetail.getTransactionStatus();
    }

    private void sendRecordMessage(Long RecordId) {
        RecordMQPO recordMQPO = new RecordMQPO();
        recordMQPO.setRecordId(RecordId);

        rabbitMQRecordProducer.sendRecord(recordMQPO);
    }


}
